home *** CD-ROM | disk | FTP | other *** search
/ The Best of MacTutor - S…e Code for Volumes 1 to 5 / The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin / Source Code / #46 (Jul 89) / MacTutor Edit Extender / EditExtender.c < prev    next >
C/C++ Source or Header  |  1988-06-08  |  12KB  |  604 lines

  1. /*  
  2.         Edit Extender Desk Accessory
  3.         for MacTutor Magazine
  4.         June 1, 1988
  5.         by Joel McNamara, Satori Software     
  6. */
  7.  
  8. /* the required stuff... */
  9. #include "EventMgr.h"
  10. #include "MenuMgr.h"
  11. #include "MemoryMgr.h"
  12. #include "FontMgr.h"
  13. #include "FileMgr.h"
  14. #include "DeviceMgr.h"
  15. #include "DialogMgr.h"
  16. #include "IntlPkg.h"
  17. #include "StdFilePkg.h"
  18.  
  19. /* the globals... */
  20. int                 ALREADY_OPEN = 0;
  21. int                    CONDITION = 0;
  22. int                    RUNCODE = 0;
  23. DCtlPtr         DCE;
  24. GrafPtr            SAVEPORT;
  25. MenuHandle    THE_MENUHANDLE;
  26.  
  27. /* the constants... */
  28.  
  29. /* this routine returns the correct resource number for the driver */
  30. #define    RsrcID(id) (0xC000 + (~DCE->dCtlRefNum << 5) + id)
  31.  
  32. /* the dialogs */
  33. #define AboutDLOG                0
  34. #define CountsDLOG            1
  35. #define    MessageDLOG            2
  36.  
  37. /* counts DITL items */
  38. #define    CharItem                2
  39. #define WordsItem                3
  40. #define SentenceItem        4
  41. #define ParagraphItem        5
  42.  
  43. /* the fake window */
  44. #define FakeWIND                0
  45.  
  46. /* run code commands */
  47. #define UpperCaseCOND        1
  48. #define LowerCaseCOND        2
  49. #define    ReverseCaseCOND    3
  50. #define    CapitalizeCOND    4
  51. #define    CountsCOND            5
  52. #define TextCOND                6
  53. #define DateCOND                7
  54. #define TimeCOND                8
  55.  
  56. /* STR# error messages */
  57. #define    ListSTR                    0
  58. #define MemoryMSG                1
  59. #define GenericMSG            2
  60. #define CreateMSG                3
  61. #define OpenMSG                    4
  62. #define WriteMSG                5
  63. #define    SelectMSG                6
  64.  
  65. /* menu items */
  66. #define AboutITEM                1
  67. #define UpperITEM                3
  68. #define LowerITEM                4
  69. #define ReverseITEM            5
  70. #define CapitalITEM            6
  71. #define DateITEM                8
  72. #define    TimeITEM                9
  73. #define CountsITEM         11
  74. #define TextITEM           13
  75. #define QuitITEM           15
  76.  
  77.  /* DA messages */
  78. #define OpenMessage            0
  79. #define ControlMessage    2
  80. #define CloseMessage        4
  81.  
  82. /* let's start... */    
  83. main(controlParam, dControl, message)
  84. cntrlParam *controlParam;
  85. DCtlPtr dControl;
  86. short message;
  87. {
  88.     EvQEl            tempQElement;
  89.         
  90.     if ((dControl->dCtlStorage) == 0) {
  91.         SysBeep(5);
  92.         if (message == OpenMessage) {
  93.             SysBeep(5);
  94.             Display(MemoryMSG);
  95.             CloseDriver(dControl->dCtlRefNum);
  96.         }
  97.         return(0);
  98.     }
  99.         
  100.     DCE = dControl;
  101.     switch (message) {
  102.         case OpenMessage:
  103.             DoOpen();
  104.         break;
  105.         
  106.         case ControlMessage:
  107.             switch (controlParam->csCode) {
  108.               /* who needs to be in control */
  109.                 case accRun:
  110.                     if ((RUNCODE != 0) && (OSEventAvail(keyDownMask,
  111.                     &tempQElement) == 0))
  112.                         DoRuncode(RUNCODE);
  113.                 break;
  114.                 
  115.                 case accMenu:
  116.                     DoMenu(controlParam->csParam[1]);
  117.                 break;
  118.                 
  119.                 case goodBye:
  120.                     DoGoodBye();
  121.                 break;
  122.             }
  123.         break;
  124.         
  125.         case CloseMessage:
  126.             DoClose();
  127.         break;
  128.     }    
  129. return(0);
  130. }
  131.  
  132. /* open the DA */
  133. DoOpen()
  134. {        
  135.     DCE->dCtlFlags |= dNeedLock|dNeedGoodBye|dCtlEnable|dNeedTime;    
  136.     DCE->dCtlDelay = 15;
  137.     DCE->dCtlMenu = RsrcID(0);
  138.     if (ALREADY_OPEN)
  139.         return;
  140.         
  141.     RUNCODE = 0;    
  142.     ALREADY_OPEN = 1;
  143.     THE_MENUHANDLE = GetMenu( DCE->dCtlMenu);
  144.     (*THE_MENUHANDLE)->menuID = DCE->dCtlMenu;
  145.     InsertMenu(THE_MENUHANDLE,0);
  146.     DrawMenuBar();
  147. }
  148.  
  149. /* handle any menu items */
  150. DoMenu(theItem)
  151. int    theItem;
  152. {
  153.     switch (theItem)
  154.         {
  155.             case AboutITEM:
  156.                 DoAbout();
  157.             break;
  158.                 
  159.             case UpperITEM:
  160.                 DoCopy();
  161.                 CONDITION = UpperCaseCOND;
  162.             break;
  163.     
  164.             case LowerITEM:
  165.                 DoCopy();
  166.                 CONDITION = LowerCaseCOND;
  167.             break;
  168.     
  169.             case ReverseITEM:
  170.                 DoCopy();
  171.                 CONDITION = ReverseCaseCOND;
  172.             break;
  173.     
  174.             case CapitalITEM:
  175.                 DoCopy();
  176.                 CONDITION = CapitalizeCOND;
  177.             break;
  178.     
  179.             case DateITEM:
  180.                 SetRuncode();
  181.                 CONDITION = DateCOND;
  182.             break;
  183.     
  184.             case TimeITEM:
  185.                 SetRuncode();
  186.                 CONDITION = TimeCOND;
  187.             break;
  188.     
  189.             case CountsITEM:
  190.                 DoCopy();
  191.                 CONDITION = CountsCOND;
  192.             break;
  193.     
  194.             case TextITEM:
  195.                 DoCopy();
  196.                 CONDITION = TextCOND;
  197.             break;
  198.                 
  199.             case QuitITEM:    
  200.                 DoClose();
  201.             break;
  202.                 
  203.             default:
  204.             break;
  205.         }
  206.     HiliteMenu(0);
  207. }
  208.  
  209. /* about us */
  210. DoAbout()
  211. {    
  212.     DialogPtr theDialog;
  213.     int dummy;
  214.     
  215.     theDialog = GetNewDialog(RsrcID(AboutDLOG),0,-1);
  216.     ModalDialog(0, &dummy);
  217.     DisposDialog(theDialog);
  218. }
  219.  
  220. /* close everything up */
  221. DoClose()
  222. {
  223.     DeleteMenu(DCE->dCtlMenu);
  224.     DisposeMenu(THE_MENUHANDLE);
  225.     ALREADY_OPEN = 0;
  226.     DCE->dCtlMenu = 0;
  227.     DCE->dCtlWindow = 0;
  228.     DrawMenuBar();
  229. }
  230.  
  231. /* good bye... */
  232. DoGoodBye()
  233. {
  234.     DCE->dCtlMenu = 0;
  235.     DCE->dCtlWindow = 0;
  236. }
  237.  
  238. /* do a control c */
  239. DoCopy()
  240. {
  241.     struct keys{
  242.     long    charCode;
  243.     long    modifiers;
  244.     } *keysPtr;
  245.     long    len;
  246.     
  247.     GetPort(&SAVEPORT);
  248.     len = ZeroScrap();
  249.     keysPtr = (struct keys*)0x174;                    
  250.     keysPtr->charCode = 0x00000000;
  251.     keysPtr->modifiers = 0x00008000;
  252.     PostEvent(3,67);
  253.     keysPtr->charCode = 0x00000000;
  254.     keysPtr->modifiers = 0x00000000;
  255.     RUNCODE = 1;
  256. }
  257.  
  258. /* get the DA's attention */
  259. SetRuncode()
  260. {
  261.     RUNCODE = 1;
  262. }
  263.  
  264. /* handle any run codes */
  265. DoRuncode(myRunCode)
  266. short    myRunCode;
  267. {
  268.     switch (myRunCode)
  269.         {
  270.             case 1: /* bring up the dummy window */
  271.                 DCE->dCtlWindow = GetNewWindow(RsrcID(FakeWIND),0,-1);
  272.                 ((WindowPeek)(DCE->dCtlWindow))->windowKind = DCE->dCtlRefNum;
  273.                 SetPort(DCE->dCtlWindow);
  274.                 RUNCODE = 2;
  275.             break;
  276.     
  277.             case 2: /* do a paste event */
  278.                 PostPaste();
  279.                 RUNCODE = 3;
  280.             break;
  281.     
  282.             case 3: /* now deal with our commands */
  283.                 DoText();
  284.             break;
  285.                 
  286.             default:
  287.             break;
  288.         }
  289. }
  290.  
  291. /* here's where we do our edit commands */
  292. DoText()
  293. {    
  294.     long        len;
  295.     long        myOffset;
  296.     long        loop;
  297.     long        temp;
  298.     long        theSecs;
  299.     
  300.     Handle    myHandle;
  301.     Handle    newHandle;
  302.     Handle    theHandle;
  303.     
  304.     Rect        itemRect;
  305.     
  306.     int            sentences;
  307.     int            paragraphs;
  308.     int            words;
  309.     int            chars;
  310.     int            itemType;
  311.     int            tempInt;
  312.     
  313.     char        myChar;
  314.     char        prevChar;
  315.     
  316.     DialogPtr    theDialog;
  317.     Ptr            myPtr;
  318.     
  319.     Str255    numStr;
  320.     Str255    timeStr;
  321.     
  322.         
  323.     RUNCODE = 0;                    
  324.     myHandle = NewHandle(0);
  325.                         
  326.     len = GetScrap(myHandle,'TEXT',&myOffset);
  327.     if ((len <= 0) && (CONDITION <= CapitalizeCOND))
  328.     /* nothing's in the scrap */
  329.         {
  330.             SysBeep(5);
  331.             Display(SelectMSG);
  332.             DisposeWindow(DCE->dCtlWindow);
  333.             DCE->dCtlWindow = 0;
  334.             SetPort(SAVEPORT);
  335.         }
  336.     else
  337.         {        
  338.         if (CONDITION < CountsCOND)
  339.         /* do we need a handle for manipulation? */
  340.             newHandle = NewHandle(GetHandleSize(myHandle));
  341.         
  342.         switch (CONDITION)
  343.         {
  344.             /* the upper routine */
  345.             case UpperCaseCOND:
  346.                 for (loop = 0; loop <= (GetHandleSize(myHandle)); loop++) 
  347.                 *(((char *)(*newHandle)) + loop) = toupper(*((char *)((long)(*myHandle) + loop)));
  348.             break;
  349.     
  350.             /* the lower case routine */
  351.             case LowerCaseCOND:
  352.                 for (loop = 0; loop <= (GetHandleSize(myHandle)); loop++) 
  353.                 *((char *)((long)(*newHandle) + loop)) = tolower(*((char *)((long)(*myHandle) + loop)));
  354.             break;
  355.         
  356.             /* the reverse case routine */
  357.             case ReverseCaseCOND:
  358.                 for (loop = 0; loop <= (GetHandleSize(myHandle)); loop++) {
  359.                     if (isupper(*((char *)((long)(*myHandle) + loop))))  
  360.                         *((char *)((long)(*newHandle) + loop)) = tolower(*((char *)((long)(*myHandle) + loop)));
  361.                     else
  362.                     if (islower(*((char *)((long)(*myHandle) + (long)loop))))  
  363.                         *((char *)((long)(*newHandle) + loop)) = toupper(*((char *)((long)(*myHandle) + loop)));
  364.                     else
  365.                         *((char *)((long)(*newHandle) + loop)) = *((char *)((long)(*myHandle) + loop));    
  366.                 }
  367.             break;
  368.     
  369.             /* the capitalization routine */        
  370.             case CapitalizeCOND:
  371.                 prevChar = (char)'x';
  372.                 for (loop = 0; loop <= (GetHandleSize(myHandle)); loop++)
  373.                 { 
  374.                     if (loop == 0)
  375.                         {
  376.                             *((char *)((long)(*newHandle) + loop)) = toupper(*((char *)((long)(*myHandle) + loop)));
  377.                             prevChar = *((char *)((long)(*newHandle) + loop));
  378.                         }
  379.                     else
  380.                         {
  381.                             if ((prevChar == ' ') || (prevChar == '\r') ||
  382.                                 (prevChar == '\t')) 
  383.                                 *((char *)((long)(*newHandle) + loop)) = toupper(*((char *)((long)(*myHandle) + loop)));                
  384.                             else
  385.                                 *((char *)((long)(*newHandle) + loop)) = *((char *)((long)(*myHandle) + loop));    
  386.                             prevChar = *((char *)((long)(*newHandle) + loop));
  387.                         }
  388.                 } 
  389.             break;
  390.     
  391.             /* a simplistic wc */
  392.             case CountsCOND:
  393.                 chars = sentences = paragraphs = words = 0;
  394.                         
  395.                 myPtr = *myHandle;
  396.                 for (temp = 0; temp <= len; temp++)
  397.                     {
  398.                         myChar = *((char *)((long)myPtr + temp));
  399.                             chars++;
  400.  
  401.                         if (myChar == '\r')
  402.                             paragraphs++;
  403.                             
  404.                         if (myChar == '.' || myChar == '!' || myChar == '?')
  405.                             sentences++;
  406.                         
  407.                         if (myChar == ' ' || myChar == '\t' || myChar == '\r')
  408.                             words++;
  409.                         }    
  410.                 
  411.                 InitCursor();            
  412.                 theDialog = GetNewDialog(RsrcID(CountsDLOG),0,-1);
  413.                 SetPort(theDialog);
  414.  
  415.                 NumToString(chars - paragraphs,numStr);
  416.                 GetDItem(theDialog,CharItem,&itemType,&theHandle,&itemRect); 
  417.                 SetIText(theHandle,numStr);
  418.                                     
  419.                 NumToString(words,numStr);
  420.                 GetDItem(theDialog,WordsItem,&itemType,&theHandle,&itemRect); 
  421.                 SetIText(theHandle,numStr);
  422.                 
  423.                 NumToString(sentences,numStr);
  424.                 GetDItem(theDialog,SentenceItem,&itemType,&theHandle,&itemRect); 
  425.                 SetIText(theHandle,numStr);
  426.                 
  427.                 NumToString(paragraphs,numStr);
  428.                 GetDItem(theDialog,ParagraphItem,&itemType,&theHandle,&itemRect); 
  429.                 SetIText(theHandle,numStr);
  430.                                         
  431.                 ModalDialog(0,&tempInt);
  432.                 CloseDialog(theDialog);
  433.             break;
  434.             
  435.             /* text to save condition */    
  436.             case TextCOND:
  437.                 Extract(myHandle);            
  438.             break;
  439.             
  440.             /* display date condition */    
  441.             case DateCOND:
  442.                 GetDateTime(&theSecs);
  443.                 IUDateString(theSecs,longDate,&timeStr);
  444.                 PtoCstr(timeStr);
  445.                 ZeroScrap();
  446.                 PutScrap(strlen(timeStr),'TEXT',&timeStr);
  447.                 PostPaste();
  448.             break;
  449.     
  450.             /* display time condition */
  451.             case TimeCOND:
  452.                 GetDateTime(&theSecs);
  453.                 IUTimeString(theSecs,TRUE,&timeStr);
  454.                 PtoCstr(timeStr);
  455.                 ZeroScrap();
  456.                 PutScrap(strlen(timeStr),'TEXT',&timeStr);
  457.                 PostPaste();
  458.             break;
  459.                 
  460.             default:
  461.             break;
  462.         }
  463.         
  464.         DisposeWindow(DCE->dCtlWindow);
  465.         DCE->dCtlWindow = 0;
  466.         SetPort(SAVEPORT);
  467.         
  468.         if (CONDITION < CountsCOND)
  469.         /* then we need to paste in the new stuff */
  470.             {
  471.                 ZeroScrap();
  472.                 PutScrap(GetHandleSize(myHandle),'TEXT',*newHandle);
  473.                 DisposHandle(newHandle);
  474.                 PostPaste();    
  475.             }                
  476.         }                    
  477.         DisposHandle(myHandle);
  478.         CONDITION = 0;
  479. }
  480.  
  481. /* do a paste event */
  482. PostPaste()
  483. {
  484.     struct keys{
  485.     long    charCode;
  486.     long    modifiers;
  487.     } *keysPtr;
  488.     
  489.         keysPtr = (struct keys*)0x174;                    
  490.         keysPtr->charCode = 0x00000000;
  491.         keysPtr->modifiers = 0x00008000;
  492.         PostEvent(3,86);
  493.         keysPtr->charCode = 0x00000000;
  494.         keysPtr->modifiers = 0x00000000;
  495. }
  496.  
  497. /* error message display */
  498. Display(theIndex)
  499. int theIndex;
  500. {
  501.     DialogPtr theDialog;
  502.     int             dummy;
  503.     Str255        theMessage;
  504.     
  505.     GetIndString(&theMessage,RsrcID(ListSTR),theIndex);
  506.     InitCursor();
  507.     theDialog = GetNewDialog(RsrcID(MessageDLOG),0,-1);
  508.     ParamText(theMessage,"\p","\p","\p");    
  509.     ModalDialog(0,&dummy);
  510.     DisposDialog(theDialog);
  511. }
  512.  
  513. /* save selected text to a file */
  514. Extract(myHandle)
  515. Handle myHandle;
  516. {
  517.     SFReply myReply;
  518.     Point     myLoc;
  519.     int            errCode, refNum;
  520.     long        theCount;
  521.     
  522.     myLoc.v = 90;
  523.     myLoc.h = 90;
  524.     
  525.     HLock(myHandle);
  526.     SFPutFile(myLoc,"\pSave selected text to:","\pUntitled",0L,&myReply);
  527.     
  528.     if (myReply.good)
  529.     {
  530.          errCode = Create(myReply.fName,myReply.vRefNum,'EDIT','TEXT');
  531.       if (errCode != noErr);
  532.           {
  533.                 if (errCode == dupFNErr) {
  534.                         FSDelete(myReply.fName,myReply.vRefNum);
  535.                         errCode = Create(myReply.fName,myReply.vRefNum,'EDIT','TEXT');
  536.               }
  537.            else if (errCode != noErr) {    
  538.                         Display(CreateMSG);
  539.                         HUnlock(myHandle);
  540.                         return;
  541.                         }
  542.             }
  543.     
  544.             if (FSOpen(myReply.fName,myReply.vRefNum,&refNum) != noErr) {
  545.                 Display(OpenMSG);
  546.                 FSClose(refNum);
  547.                 HUnlock(myHandle);
  548.                 return;
  549.                 }
  550.     
  551.             theCount = GetHandleSize(myHandle);
  552.         if (FSWrite(refNum,&theCount,*myHandle) != noErr) {
  553.                 Display(WriteMSG);
  554.                 FSClose(refNum);
  555.                 HUnlock(myHandle);
  556.                 return;
  557.                }
  558.                
  559.         FSClose(refNum);
  560.     }
  561.     HUnlock(myHandle);
  562. }
  563.  
  564.  
  565. /* just in case your compiler doesn't already have these...
  566.    otherwise, leave them out... */
  567.    
  568. strlen(s)
  569. register char *s;
  570. {
  571.     char *s0 = s;
  572.     
  573.     while (*s++);
  574.     return (s-s0-1);
  575. }
  576.  
  577.  
  578. int    toupper(c)
  579. char    c;
  580. {
  581.     return((c>='a') && (c<='z') ? (c-32) : c);
  582. }
  583.  
  584.  
  585. int    tolower(c)
  586. char    c;
  587. {
  588.     return((c>='A') && (c<='Z') ? (c+32) : c);
  589. }
  590.  
  591.  
  592. int    isupper(c)
  593. char c;
  594. {
  595.     return((c>='A') && (c<='Z'));
  596. }
  597.  
  598.  
  599. int    islower(c)
  600. char c;
  601. {
  602. return((c>='a') && (c<='z'));
  603. }
  604.